package org.ouwh.fw.threadpool;

import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.ouwh.fw.model.data.Struct;
import org.ouwh.fw.model.service.Service;

public class ThreadPoolService extends Service {
	private static final String ACTIVE_TASKS_INFO = "active-tasks-info";
	private static final String FREE_THREAD_COUNT = "free-thread-count";
	private static final String SIZE = "size";
	private static final String FREE_TIME_SIZE = "free-time-size";
	private static final String BUSY_TIME_SIZE = "busy-time-size";
	private static final String FREE_TIME = "free-time";
	private static final String THREAD_POOL_CLASS = "thread-pool-class";
	private static Log log = LogFactory.getLog(ThreadPoolService.class);
	private IThreadPool threadPool = null;
	private String poolClassName;
	private String freeTime;
	private int freeTimeSize;
	private int busyTimeSize;

	protected void init(Properties props) {
		poolClassName = props.getProperty(THREAD_POOL_CLASS);
		freeTime = props.getProperty(FREE_TIME);
		busyTimeSize = Integer.parseInt(props.getProperty(BUSY_TIME_SIZE));
		freeTimeSize = Integer.parseInt(props.getProperty(FREE_TIME_SIZE));
	}

	@Override
	protected void startup() throws Exception {
		if (threadPool == null) {
			Class<?> clazz = Class.forName(poolClassName);
			threadPool = (IThreadPool) clazz.newInstance();
			threadPool.setPoolName(getId());
			threadPool.setFreeTime(freeTime);
			threadPool.setBusyTimeSize(busyTimeSize);
			threadPool.setFreeTimeSize(freeTimeSize);
			threadPool.initialize();
			log.info("ThreadPool[" + getId() + "]started");
		}
	}

	@Override
	protected void reset(Properties props) throws Exception {
		freeTime = props.getProperty(FREE_TIME);
		busyTimeSize = Integer.parseInt(props.getProperty(BUSY_TIME_SIZE));
		freeTimeSize = Integer.parseInt(props.getProperty(FREE_TIME_SIZE));
		String tmpClassName = props.getProperty(THREAD_POOL_CLASS);
		if (tmpClassName.equals(poolClassName)) {
			threadPool.setBusyTimeSize(busyTimeSize);
			threadPool.setFreeTimeSize(freeTimeSize);
			try {
				threadPool.setFreeTime(freeTime);
				log.info("ThreadPool[" + getId() + "]resetted without restart.");
			} catch (Exception e) {
				log.error("ThreadPool[" + getId() + "]schedule error", e);
			}
		} else {
			poolClassName = tmpClassName;
			stop();
			start();
			log.info("ThreadPool[" + getId() + "]resetted by restart.");
		}
	}

	protected void shutdown() {
		if (threadPool != null) {
			log.info("ThreadPool[" + getId() + "]stopping...");
			threadPool.terminate();
			threadPool = null;
			log.info("ThreadPool[" + getId() + "]stopped.");
		}
	}

	@Override
	protected void dumpToStruct(Struct struct) {
		struct.addData(THREAD_POOL_CLASS, poolClassName);
		struct.addData(FREE_TIME, freeTime);
		struct.addData(BUSY_TIME_SIZE, threadPool.getBusyTimeSize());
		struct.addData(FREE_TIME_SIZE, threadPool.getFreeTimeSize());
		struct.addData(SIZE, threadPool.size());
		struct.addData(FREE_THREAD_COUNT, threadPool.getFreeThreadCount());
		struct.addData(ACTIVE_TASKS_INFO, threadPool.getActiveTasksInfo());

	}

	public void put(IThreadPoolTask task) throws Exception {
		threadPool.put(task);
	}

	public void waitPut(IThreadPoolTask task, long timeout) throws Exception {
		threadPool.waitPut(task, timeout);
	}

	public boolean isAllThreadFree() {
		return threadPool.isAllThreadFree();
	}

}
